<template>
    <div>
      <h2 style="text-align: center; color: red">ES6部分知识小结</h2>

     <el-button @click="defineproperties">defineproperties</el-button>
     <el-button @click="changethis" type="danger">改变this指向问题</el-button>
     <el-button @click="jiegoufuzhi" type="danger">解构赋值</el-button>
     <el-button @click="spreaded"type="success" >扩展运算符</el-button>
     <el-button @click="arrow" type="danger" disabled>箭头函数</el-button>
     <el-button @click="ES6module" type="info" disabled >ES6模块化问题</el-button>

     <div style="margin-top: 30px"></div>

     <el-button @click="symbol" type="info" >Symbol相关(了解)</el-button>
     <el-button @click="diedaiqi" type="" >iterator迭代器(了解)</el-button>
     <el-button @click="generator" type="warning" >generator生成器</el-button>
     <el-button @click="generator2" type="warning" >generator生成器2</el-button>

     <el-button @click="fetchhanshu" type="" >fetch的基本使用</el-button>
      <div style="margin-top: 30px"></div>


    </div>
</template>

<script>

    export default {
      name: "ES6",
      components: {},
      data() {
        return {}
      },
      computed: {},
      methods: {
        defineproperties() {
          let obj2 = {firstName: "mark", lastName: "tuwen"};
          Object.defineProperties(obj2, {
            fullName: {
              get: function () {
                return this.firstName + " " + this.lastName;
              },
              set: function (name) {
                console.log("hello")
                var names = name.split(" ");
                this.firstName = names[0];
                this.lastName = names[1];
              }

            }
          });
          console.log(obj2.fullName);//自动调用fullName的get方法
          obj2.fullName = 'mark json';//自动调用fullName的set方法
          console.log(obj2.fullName);//自动调用fullName的get方法
        },

        changethis() {
          //使用call apply bind 改变 this的指向
          var wf = {name: 'wf'};
          var a = {
            name: 'wfwf',
            f1() {
              console.log(this.name);
            },
            f2() {
              setTimeout(() => {
                this.f1();
              }, 100)

            }
          }
          a.f2()//wfwf

          setTimeout(function () {
            console.log(this)
          }.call(wf), 100)
          // .call||apply||bind(a)  bind要单独执行一下()，第一个参数使作用域对象 即this的指向
        },

        jiegoufuzhi() {
          //1. 数组的结构
          const F4 = ['小沈阳', '刘能', '赵四', '宋小宝'];
          let [xiao, liu, zhao1, song] = F4;
          console.log(xiao, liu, zhao1, song)
          //2. 对象的解构
          const zhao = {
            name: '赵本山',
            age: '不详',
            xiaopin: function () {
              console.log("我可以演小品");
            }
          };

          //单独解出函数,调用时,zhao都不用写；单独解出其中某个属性
          let {xiaopin} = zhao;
          let {name, age} = zhao
          console.log(name, age)
          xiaopin();
          xiaopin();

          //连续结构赋值  与重命名
          let obj ={a:{b:{c:"20"}}}
          let {a:{b:{c:value}}} = obj

          console.log(value)
      /*  let {a:{b:{c}}} = obj
          console.log(c)*/
        },


        spreaded() {
          //扩展运算符的应用
          //1. 数组的合并
          const kuaizi = ['王太利', '肖央'];
          const fenghuang = ['曾毅', '玲花'];
          const zuixuanxiaopingguo = [...kuaizi, ...fenghuang];


          //2. 扩展运算符:数组的克隆★★★
          const sanzhihua = ['E', 'G', 'M'];
          const sanyecao = [...sanzhihua];//  ['E','G','M']


          //3...在函数中使用
          function sum(...numbers) {
            return numbers.reduce((preValue, currentValue) => {
              return preValue + currentValue
            })
          }

          console.log(sum(1, 2, 3, 4));
          //4.

          //构造字面量对象时使用展开语法
          let person = {name: 'tom', age: 18}
          //这种算是浅拷贝
          let person2 = {...person}
          //console.log(...person); //报错，展开运算符不能展开对象
          person.name = 'jerry'
          console.log(person2);
          console.log(person);

          //对象的修改与合并
          let person3 = {...person, name: 'jack', address: "地球"}
          console.log(person3);

        },

        arrow() {

          /*
            箭头函数的特点:
            1. this 是静态的. this 始终指向  函数声明时  所在作用域下的 this 的值(就近原则)(谁调用指向谁)
               无论用call,apply都不能改变this的指向
            2. 不能作为构造实例化对象  不能new一个对象
            3. 不能使用 arguments 变量
            4. 简写方式：
                 省略小括号, 当形参有且  只有一个的时候
                 省略花括号, 当代码体  只有一条语句的时候, 此时 return  必须省略★★★
                 而且语句的执行结果就是函数的返回值★★★
           */

        },
        ES6module(){
          //找百度
        },

        symbol(){
         /* Symbol(第七种数据类型  类似String)
            1) Symbol 的值是唯一的，用来解决命名冲突的问题(声明变量  声明方法都可以)
            2) Symbol 值不能与其他数据进行运算
            3) Symbol 定义的对象属性不能使用 for…in 循环遍历，但是可以使用*/
          //声明一个对象
          const banji = {
            name: "终极一班",
            stus: [
              'xiaoming',
              'xiaoning',
              'xiaotian',
              'knight'
            ],
            [Symbol.iterator]() {
              //自定义遍历数组
              //索引变量
              let index = 0;
              //
              let _this = this;
              return {
                next: function () {
                  if (index < _this.stus.length) {
                    const result = { value: _this.stus[index], done: false };
                    //下标自增
                    index++;
                    //返回结果
                    return result;
                  }else{
                    return {value: undefined, done: true};
                  }
                }
              };
            }
          }
          //遍历这个对象  自定义 for of 访问对象的属性里的数组
          for (let v of banji) {
            console.log(v);
          }
        },
        diedaiqi(){
          //迭代器  (了解)
        },
        generator(){
          //生成器其实就是一个特殊的函数
          //异步编程★★★  纯回调函数  node fs  ajax mongodb  解决回调地狱（控制多个异步函数之间的执行顺序★★★）
          function one(){
            setTimeout(()=>{
              console.log(111);
              iterator.next();
            },1000)
          }

          function two(){
            setTimeout(()=>{
              console.log(222);
              iterator.next();
            },2000)
          }

          function three(){
            setTimeout(()=>{
              console.log(333);
              iterator.next();
            },3000)
          }
          // 声明生成器函数,放入需要异步执行的函数
          function * gen(){
            yield one();
            yield two();
            yield three();
          }

          //调用生成器函数
          let iterator = gen();
          iterator.next();


        },
        generator2(){
          //模拟获取  用户数据  订单数据  商品数据
          function getUsers(){
            setTimeout(()=>{
              let data = '用户数据';
              //调用 next 方法, 并且将数据传入
              //第二次调用,实参将作为第一个yield返回的结果
              iterator.next(data);
            }, 1000);
          }

          function getOrders(){
            setTimeout(()=>{
              let data = '订单数据';
              //第三次调用,实参将作为第二个yield返回的结果
              iterator.next(data);
            }, 1000)
          }

          function getGoods(){
            setTimeout(()=>{
              let data = '商品数据';
              //第四次调用,实参将作为第三个yield返回的结果
              iterator.next(data);
            }, 1000)
          }

          function * gen(){
            let users = yield getUsers();
            console.log(users);

            let orders = yield getOrders();
            console.log(orders);

            let goods = yield getGoods();
            console.log(goods)
          }

          //调用生成器函数
          let iterator = gen();
          iterator.next();

        },

        fetchhanshu(){
          //fetch的基本使用（了解）
          /*  window.fetch('https://api.apishop.net/common/dogFamily/queryDogListByKeyword?
                                  apiKey=r6g1BIXa41c8c9c2b979ae5d8ad03f9fd478e74a347e4ab&keyword=金毛犬')
            .then(response => response.json()) //定义返回的类型和数据格式
            .then(data => console.log(data)) // 返回的数据
*/
        },

      }
    }
</script>

<style scoped>

</style>
<!--
      对象的几个扩展方法
      Object.entries(obj)
      Object.keys(obj)
      Object.values(obj)

         JSON.stringify(obj/arr):js对象||数组转换为json对象||数组
         JSON.parse(json):json对象(数组)转换为js对象(数组)

         Object.create  方法创建一个新对象，使用现有的对象来提供新创建的对象的__proto__
          var objExt = Object.create(obj,{
             sex:{
              value:'男',
              writable:true,//属性是否能修改。默认false
              configurable:true,//属性是否能被删除。默认false
              enumerable:true//属性是否能用 fro in枚举，默认false
    }
  })


         Object.defineProperties： 方法直接在一个对象上定义新的属性或修改现有属性，并返回该对象。
         Object.defineProperties(object,propertyDescriptors）的定义
         object给哪个对象增加属性。
         propertyDescriptors 对增加的属性进行描述。
         propertyDescriptors 用来描述属性的。可以有下面几个参数。
         get 属性的get方法:获取当前属性值的回调函数
         set 属性的set方法:修改当前属性值时触发的回调函数,实参为修改之后的值

          const声明的普通变量不能修改  声明的{}只可以改变属性不可改变指向
-->
<!--

        rest 参数(不限定参数个数)问题  必须要放到参数最后
        function fn(a,b,...args){
            console.log(a);
            console.log(b);
            //args参数会被放入数组
            console.log(args);
        }
        fn(1,2,3,4,5,6);


-->

